package org.xxpay.pay.channel.huypay;

import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Service;
import org.xxpay.core.common.constant.MchConstant;
import org.xxpay.core.common.constant.PayConstant;
import org.xxpay.core.common.util.AmountUtil;
import org.xxpay.core.common.util.JsonUtil;
import org.xxpay.core.common.util.MyLog;
import org.xxpay.core.entity.PayOrder;
import org.xxpay.pay.channel.BasePayNotify;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

@Service
public class HuypayPayNotifyService extends BasePayNotify {

    private static final MyLog _log = MyLog.getLog(HuypayPayNotifyService.class);
    private static final String logPrefix = "【处理"+ HuypayConfig.CHANNEL_NAME+"支付回调】";

    @Override
    public String getChannelName() {
        return HuypayConfig.CHANNEL_NAME;
    }

    @Override
    public JSONObject doNotify(Object notifyData) {
        _log.info("====== 开始处理{}支付回调通知 ======", getChannelName());
        HttpServletRequest request = (HttpServletRequest) notifyData;
        JSONObject retObj = buildRetObj();
        Map<String, String> payContext = new HashMap();

        String respString = HuypayConfig.RETURN_VALUE_ERROR;
        try {
            PayOrder payOrder = verifyPayParams(request, payContext);
            if( payOrder == null ) { //验证参数失败
                retObj.put(PayConstant.RESPONSE_RESULT, HuypayConfig.RETURN_VALUE_ERROR);
                return retObj;
            }
            //订单已经支付完成
            if(payOrder.getStatus() == PayConstant.PAY_STATUS_SUCCESS || payOrder.getStatus() == PayConstant.PAY_STATUS_COMPLETE){
                retObj.put(PayConstant.RESPONSE_RESULT, HuypayConfig.RETURN_VALUE_SUCCESS);
                return retObj;
            }
            //上游通知 状态
            String channelOrderNo = payContext.get("queryId"); //上游订单号

            int updatePayOrderRows = commonService.payOrderService.updateStatus4Success(payOrder.getPayOrderId(), channelOrderNo);
            if (updatePayOrderRows != 1) {
                _log.error("{}更新支付状态失败,将payOrderId={},更新payStatus={}失败", logPrefix, payOrder.getPayOrderId(), PayConstant.PAY_STATUS_SUCCESS);
                retObj.put(PayConstant.RESPONSE_RESULT, "处理订单失败");
                return retObj;
            }
            _log.error("{}更新支付状态成功,将payOrderId={},更新payStatus={}成功", logPrefix, payOrder.getPayOrderId(), PayConstant.PAY_STATUS_SUCCESS);
            payOrder.setStatus(PayConstant.PAY_STATUS_SUCCESS);

            // 业务系统后端通知
            baseNotify4MchPay.doNotify(payOrder, true);

            //推送ws消息到浏览器
            wsPayOrderServer.sendMsgByOrderId(payOrder.getPayOrderId(), PayConstant.PAY_STATUS_SUCCESS, payOrder.getReturnUrl());
            _log.info("====== 完成处理{}支付回调通知 ======", getChannelName());
            respString = HuypayConfig.RETURN_VALUE_SUCCESS;
        } catch (Exception e) {
            _log.error(e, logPrefix + "处理异常");
        }
        retObj.put(PayConstant.RESPONSE_RESULT, respString);
        return retObj;
    }

    /**
     * 验证通知参数
     * @return
     */
    public PayOrder verifyPayParams(HttpServletRequest request, Map<String, String> payContext) {

        // 校验结果是否成功
        String merid = request.getParameter("merid");		    // 商户号
        String mchorderno = request.getParameter("mchorderno");	// 商户订单号
        String billno = request.getParameter("billno");		    // 云美集订单号{用于退款}
        String tranamt = request.getParameter("tranamt");        // 交易金额
        String finishtime = request.getParameter("finishtime");  // 交易完成时间

        _log.info("[{}]merid={}, mchorderno={}, billno={}, tranamt={}, finishtime={}",
                logPrefix, merid, mchorderno, billno, tranamt, finishtime);

        // 查询payOrder记录
        String payOrderId = mchorderno;
        PayOrder payOrder = commonService.payOrderService.findByPayOrderId(payOrderId);
        if (payOrder == null) {
            _log.error("Can't found payOrder form db. payOrderId={}, ", payOrderId);
            return null;
        }

        // 金额校验
        long amount = Long.parseLong(AmountUtil.convertDollar2Cent(tranamt));
        if (amount != payOrder.getAmount().longValue()) {
            _log.error("金额不一致. outPayAmt={},payOrderId={}", amount, payOrderId);
            return null;
        }

        HuypayConfig huypayConfig = new HuypayConfig(getPayParam(payOrder));
        if(!huypayConfig.getMerId().equals(merid)) {
            _log.error("商户号不一致. dbMerid={},merid={}", huypayConfig.getMerId(), merid);
            return null;
        }

        // 查询订单状态
//        String oritranstatus = orderQuery(billno, huypayConfig);
//        if (!"01".equals(oritranstatus)) {
//            _log.error("订单状态错误payorderId={}, status={}", payOrderId, oritranstatus);
//            return null;
//        }

        payContext.put("queryId", merid);
        return payOrder;
    }

    private String orderQuery(String billno, HuypayConfig huypayConfig) {
        // 查询订单状态
        Map<String, Object> post= new TreeMap<>();
        post.put("billno", billno); // 云美集订单号
        post.put("merid", huypayConfig.getMerId()); // 商户ID
        //生成签名
        Map<String, Object> post1 = new TreeMap<>();
        post1.put("app_key", huypayConfig.getAppKey()); // 应用账号
        post1.put("method", "trade.query"); // 接口名称
        post1.put("timestamp", System.currentTimeMillis()/1000); // 时间戳
        post1.put("version", "1.0.1"); // 商户ID
        Map<String, Object> post2 = new TreeMap<>();
        post2.putAll(post);
        post2.putAll(post1);
        JSONObject json = new JSONObject(post);
        post1.put("biz_content", json.toJSONString()); //合并真正提交的参数JSON
        post1.put("sign", HuypayUtils.getSign(post1, huypayConfig.getAppSecret()));//商户密钥,请自行修改
        _log.info("{}请求数据:{}", getChannelName(), post1);
        String params = HuypayUtils.genUrlParams(post1);
        String result = HuypayUtils.sendPostJson(huypayConfig.getReqUrl(), params);
        _log.info("{}返回数据:{}", getChannelName(), result);
        JSONObject jsonObject = JsonUtil.getJSONObjectFromJson(result);
        String oritranstatus = jsonObject.getString("oritranstatus");
        return oritranstatus;
    }

}
